package com.koalac.ironman.common.adapter;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.List;
import java.util.Map;

import android.content.Context;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;

public class CommonAdapter<T> extends BaseAdapter implements NotifyDataSetChanged {
	protected int customXmlName;
	protected List<T> list;
	protected Context context;
	protected NotifyDataLoadFinished notifyDataLoadFinished;
	protected Map<String, Object> params;
	protected Callback<Object, Object> callback;
	protected Class<? extends ViewHolderModel<T>> clazz;
	
	public CommonAdapter(){
	}

	public CommonAdapter(Class<? extends ViewHolderModel<T>> clazz, List<T> list, Context context, int customXmlName) {
		this.context = context;
		this.list = list;
		this.customXmlName = customXmlName;
		this.clazz = clazz;
	}

	public NotifyDataLoadFinished getNotifyDataLoadFinished() {
		return notifyDataLoadFinished;
	}

	public void setNotifyDataLoadFinished(NotifyDataLoadFinished notifyDataLoadFinished) {
		this.notifyDataLoadFinished = notifyDataLoadFinished;
	}

	public Callback<Object, Object> getCallback() {
		return callback;
	}

	public void setCallback(Callback<Object, Object> callback) {
		this.callback = callback;
	}

	public void setParams(Map<String, Object> params) {
		this.params = params;
	}

	@Override
	public int getCount() {
		return list.size();
	}

	public void setLayoutName(int name) {
		if (name <= 0) {
			return;
		}
		customXmlName = name;
	}

	@Override
	public T getItem(int position) {
		if (position < list.size()) {
			return list.get(position);
		} else {
			return null;
		}
	}

	@Override
	public long getItemId(int position) {
		return position;
	}

	@Override
	public View getView(int position, View convertView, ViewGroup parent) {
		if (getItem(position) != null) {
			ViewHolderModel<T> instance = null;
			if (convertView == null) {
				convertView = preInitViewHolder(position, convertView, parent);
				try {
					Class<?>[] parameterTypes = { Context.class, List.class };
					Constructor<? extends ViewHolderModel<T>> constructor = clazz.getConstructor(parameterTypes);
					Object[] parameters = { context, list };
					instance = constructor.newInstance(parameters);
					instance.setNotifyDataSetChanged(this);
					instance.setCallback(callback);
					instance.initViewHoler(position, convertView);
					convertView.setTag(instance);
				} catch (InstantiationException e) {
					Log.e("创建实例-1-InstantiationException", e.getMessage(), e);
				} catch (IllegalAccessException e) {
					Log.e("创建实例-2-IllegalAccessException", e.getMessage(), e);
				} catch (SecurityException e) {
					Log.e("创建实例-3-SecurityException", e.getMessage(), e);
				} catch (NoSuchMethodException e) {
					Log.e("创建实例-4-NoSuchMethodException", e.getMessage(), e);
				} catch (IllegalArgumentException e) {
					Log.e("创建实例-5-IllegalArgumentException", e.getMessage(), e);
				} catch (InvocationTargetException e) {
					Log.e("创建实例-6-InvocationTargetException", e.getMessage(), e);
				}
			} else {
				instance = (ViewHolderModel<T>) convertView.getTag();
			}
			if (convertView != null && instance != null) {
				instance.setParams(params);
				instance.setViewHolerValues(position, convertView);
				if (position == list.size() - 1 && notifyDataLoadFinished != null) {
					notifyDataLoadFinished.onDataLoadFinished(position);
				}
			}
		}
		return convertView;
	}

	protected View preInitViewHolder(int position, View convertView, ViewGroup parent) {
		convertView = LayoutInflater.from(context).inflate(customXmlName, null);
		return convertView;
	}

	/**
	 * 配器的内容改变时需要强制调用getView来刷新每个Item的内容，会重绘控件
	 */
	@Override
	public void setNotifyDataSetChanged() {
		notifyDataSetChanged();
	}

	/**
	 * 数据集失效，重绘当前可见区域
	 */
	@Override
	public void seNotifyDataSetInvalidated() {
		notifyDataSetInvalidated();
	}
	
	public void addAll(List<T> list){
		this.list.addAll(list);
		setNotifyDataSetChanged();
	}
	
	public void clear(){
		this.list.clear();
	}
}